<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
    Documentation for Lua Lanes
-->

<html>
<head>
  <meta name="description" content="Lua Lanes - multithreading in Lua" />
  <meta name="keywords" content="Lua, Library, Multithreading, Threads, Rocks" />

  <title>Lua Lanes - multithreading in Lua</title>
</head>

<body>
<div class="header">
<hr />

<center>
<table summary="Lua logo">
  <tbody>
    <tr>
      <td align="center">
      <a href="http://www.lua.org">
        <img src="multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
        <img src="multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
        <img src="multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
        <img src="multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
        <img src="multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
      </a></td>
    </tr>
    <tr>
      <td align="center" valign="top"><h1>Lua Lanes - multithreading in Lua</h1>
      </td>
    </tr>
  </tbody>
</table>

<p class="bar">
  <a href="#description">Description</a> &middot;
  <a href="#systems">Supported systems</a> &middot;
  <a href="#installing">Installing</a> &middot;
  <a href="#using">Using</a>
</p><p class="bar">
  <a href="#creation">Creation</a> &middot;
  <a href="#results">Results</a> &middot;
  <a href="#errors">Error recovery</a> &middot;
  <a href="#cancelling">Cancelling</a>
</p><p class="bar">
<!--  <a href="#misc">Misc</a> &middot; -->
  <a href="#lindas">Lindas</a> &middot;
  <a href="#timers">Timers</a> &middot;
  <a href="#other">Other</a>
</p><p class="bar">
  <a href="#changes">Change log</a> <!-- &middot;
  <a href="comparison.html">Comparisons</a>-->
  <!-- ... -->

<p><br/><font size="-1"><i>Copyright &copy; 2007-08 Asko Kauppi. All rights reserved.</i>
    <br>Lua Lanes is published under the same <A HREF="http://en.wikipedia.org/wiki/MIT_License">MIT license</A> as Lua 5.1.
    </p><p>This document was revised on 16-Jul-08, and applies to version 2008.
</font></p>

</center>
</div>


<!-- description +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="description">Description</h2>

<p>Lua Lanes is a portable, message passing multithreading library providing
    the possibility to run multiple Lua states in parallel. It is intended to
    be used for optimizing performance on multicore CPU's s.a. <i>Intel Core Duo&trade;</i> series.
</p><p>
    Lanes is a Lua module, included into your software by the regular
    <tt>require "lanes"</tt> method. No C side programming is needed to use
    Lanes; all APIs are Lua side, and most<sup>(1</sup> existing extension modules should
    work seamlessly together with the multiple lanes (they need to be require'd
    separately into each lane, though).
</p><p>
    <h3>Features:</h3>

  <ul><li>master/sub state model
        <ul><li>any state can launch substates</li>
        </ul><br/></li>

      <li>transparent data passing</li>
        <ul><li>most Lua data types can be passed transparently between the states</li>
            <li>data passing happens using fast state-to-state copies, no serialization required</li>
        </ul><br/></li>

      <li>priorities</li>
        <ul><li>threads can be given priorities of -2..+2 (default is 0).</li>
        </ul><br/></li>

<!--
      <li>grouping the lanes
        <ul><li>allows waiting for multiple lanes to finish, or to send a message</li>
            <li>no limitations; waiting for 1000's of lanes is okay :)</li>
        </ul><br/></li>
-->
      <li>keeper tables <i>(Jun-08)</i>
        <ul><li>inter-lane data sharing using table-like constructs</li>
        </ul><br/></li>

      <li>no application level locking - ever! :)</li>
    </ul>


<h3>Limitations:</h3>

  <ul><li>requires the states to run within the same process (current
          implementation does, this can be altered with serialization)</li>
            <br/>

      <li>priorities don't work with Linux in user mode (nothing we can do about it)</li>
            <br/>

      <li>coroutines, cyclic tables and metatables cannot be passed between states</li>
            <br/>
  </ul>
</p>


<!-- systems +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="systems">Supported systems</h2>

<p>Lua Lanes supports the following operating systems:

    <ul>
        <li>Mac OS X PowerPC / Intel</li>
        <li>Linux x86 / ARM</li>
        <li>Windows XP (Win32)</li>
        <li>BSD</li>
    </ul>
    
    <p>The underlying threading code can be compiled either towards Win32 API, 
    or <a TARGET="_blank" HREF="http://en.wikipedia.org/wiki/POSIX_Threads">Pthreads</a>. Unfortunately, thread prioritation under Pthreads is a JOKE, 
    requiring OS specific tweaks and guessing undocumented behaviour. Other
    features should be portable to any modern platform.
    </p>
</p>


<!-- installing +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="installing">Installing</h2>

<p>Lua Lanes is intended to be installed via the Lua Rocks initiative.

<pre>
  > luarocks search lanes
    ... output listing Lua Lanes is there ...

  > luarocks install lanes
    ... output ...
</pre>

<p>Otherwise, see README, Makefile and source code for clues on how to install.
</p>


<!-- using +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="using">Using</h2>

<p>Steps to using Lua Lanes:
</p>

<ol>
    <li><tt>require "lanes"</tt>
        <br>- initializes the Lanes module
    </li><br/>

    <li>preparation
        <br>- gives a function, set of standard libs, globals and options for a lane
        <br>- returns a handle, calling which launches a new OS thread
    </li><br/>
    
    <li>launching
        <br>- each launch may have different arguments to that lane's function
        <br>- the code starts executing directly at the launch, on the background
    </li><br/>

    <li>controlling (optional)
        <br>- master can open <i>keeper states</i> (any number) for communication with its siblings
        <br>- support (atomic) for FIFO 1-to-1, 1-to-N or M-to-N
        <br>- more advanced constructs (s.a. worker pools, priority queues) can be crafted on top
        <br>- master can cancel a thread it created at any time
    </li><br/>

    <li>reading results
        <br>- results are provided via <tt>lane_h:unpack()</tt>, or alternatively 
            as the <tt>[1]..[N]</tt> indices of the lane handle.
        <br>- pending (<tt>wait==true</tt>), peeking
            (<tt>nil</tt> if lane is still executing) or with a timeout.
    </li>
</ol>

<p>The late evaluation of lane results makes them behave like <A TARGET="_blank" HREF="http://en.wikipedia.org/wiki/Future_%28programming%29">futures</A>.
</p>

<p><i>NOTE: globals given in lane preparation are not common between the lanes.
Each lane has its own copy, and cannot see or modify other lanes' globals.
</i></p>

<p>Basic sample:
</p>

<!-- TBD: would be REALLY nice have Lumikki do Lua source highlighting,
            when placing such code blocks on a page... :D -->
            
<table border=1 bgcolor="#FFFFE0" width=500><tr><td>
<pre>
  require "lanes"

  local f= lanes.new( function(n) return 2*n end )
  local l1= f(1)
  local l2= f(2)

  print( l1[1], l2[1] )     -- 2    4
</pre>
</table>

<p>Sample with communications:
</p>

<table border=1 bgcolor="#FFFFE0" width=500><tr><td>
<pre>
  require "lanes"

  local function body( comm, id )
    while true do
        local a,b= unpack( comm:receive("->"..id)() )   -- expects {a,b}
        comm:send( "<-"..id, { b,a } )
    end     -- never ends
  end

  local f= lanes.new "base" ( body )
  local comms= lanes.linda()

  local L1= f( comms, 1 )
  local L2= f( comms, 2 )

  comms:send( "1->", { 'a','b' } )
  comms:send( "2->", { 10, 50 } )

  for i=1,2 do
    local v= comms:wait( "1<-", "2<-" )
    print( unpack(v) )     -- b a / 50 10
  end
</pre></table>


<!-- launching +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="creation">Creation</h2>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>func= lanes.new [libs_str | opt_tbl [...]] ( lane_func )
    <br/><br/>
    lane_h= func( ... )</code>
</table>

<p>Prepares <tt>lane_func</tt> to be the main chunk for new lanes. Such
    function must not use upvalues, global (non-library) functions or anything not contained
    within the function itself. 
    If needed, one can group multiple functions into an enclosing function, so
    they become an enclosing chunk.
</p><p>
    The 'modifiers' provided between the <tt>prepare</tt> name and the
    <tt>lane_func</tt> are either string, or table. There can be any number
    of them.
</p><p>

    <code>libs_str</code> defines the standard libraries made available to the
    new Lua state:
    <table>
        <tr><td/><td></td><td>no standard libraries</td></tr>
        <tr><td width=40><td><tt>base</tt> or empty string</td>
            <td>root level names, <tt>print</tt>, <tt>assert</tt>, <tt>unpack</tt> etc.</td></tr>
        <tr><td/><td><tt>coroutine</tt></td><td><tt>coroutine.*</tt> namespace (part of base in Lua 5.1)</td></tr>
        <tr><td/><td><tt>debug</tt></td><td><tt>debug.*</tt> namespace</td></tr>
        <tr><td/><td><tt>io</tt></td><td><tt>io.*</tt> namespace</td></tr>
        <tr><td/><td><tt>math</tt></td><td><tt>math.*</tt> namespace</td></tr>
        <tr><td/><td><tt>os</tt></td><td><tt>os.*</tt> namespace</td></tr>
        <tr><td/><td><tt>package</tt></td><td><tt>package.*</tt> namespace and <tt>require</tt></td></tr>
        <tr><td/><td><tt>string</tt></td><td><tt>string.*</tt> namespace</td></tr>
        <tr><td/><td><tt>table</tt></td><td><tt>table.*</tt> namespace</td></tr>
        <br/>
        <tr><td/><td><tt>lanes</tt></td><td><tt>lanes.*</tt> namespace</td></tr>
        <br/>
        <tr><td/><td><tt>*</tt></td><td>all standard libraries, and <tt>send</tt></td></tr>
    </table>

</p><p>
    Initializing the standard libs takes a bit of time at each lane invocation.
    This is the main reason why "no libraries" is the default. It will only
    matter if you do fine grained multithreading (i.e. launch a lot of lanes).
</p><p>
    Multiple libraries can be specified either in the same string with comma(s)
    (<tt>"math,io"</tt>) or by using multiple modifiers (<tt>"math" "io"</tt>).
    You can use this effect to make your own modified prepare-variant, which
    i.e. has your favourite set of default libraries, and/or options.
</p><p>
    <i>Note: In Lua 5.1, <tt>'coroutine'</tt> namespace is part of the base library.
    This may not be the case in later versions, so explicit use of "coroutine"
    is recommended, if the lane intends to use them.</i>
</p><p>

    <code>opt_tbl</code> is a collection of options to control the way
    lanes are run:
</p><p>
  <table>
    <tr valign=top><td width=40><td>
        <code>.priority</code> : -2..+2</td>
        <td>The priority of lane(s). -2 is lowest, +2 is highest.
        <p>
    Note that implementation and dependability of priorities varies
    by platform. Especially Linux 2.6 is not supporting priorities in user mode.
    </td></tr>

    <tr valign=top><td/><td>
        <code>.cancelstep</code> : N / true / false (default)</td>
    <td>
    By default, lanes are only cancellable when they explicitly call <tt>receive()</tt>.
    With this option, one can set cancellation check to occur every <tt>N</tt>
    Lua statements. The value <tt>true</tt> uses a default value (currently 100).
    <p>
    If you want to cancel your subthreads, either place <tt>receive()</tt>
    commands in them, or set a cancelstep. The smaller the value, the faster 
    substates will react, but they'll use more CPU time testing for it.
    </td></tr>

    <tr valign=top><td/><td>
        <code>.globals</code> : globals_tbl</td>
    <td>
    Sets the globals table for the launched threads. This can be used for giving
    them constants, and/or storing a reconcilable state in connection with
    'cancel'.
    </p><p>
    <i>NOTE: The global values of various threads are in no manner connected;
    modifying one will only affect the particular state.</i>
    </td></tr>

    <tr valign=top><td/><td>
        <code>lazy</code> : true / false (default)</td>
    <td>
    Sets the eagerness of evaluation. Eager lanes (default) begin executing
    right ahead, and may get their results evaluated before they are actually
    required (good use of multithreading).
    </p><p>
    Lazy lanes won't be using up CPU power until once their values are truly
    required (if ever). This may be useful i.e. for Makefile-like flow processing,
    where all the relationships are described up front, but maybe only some of
    the end results are actually required to be built. An eager solution would
    start all builds, in parallel, always.
    </td></tr>
  </table>
</p><p>

    The function returned by <tt>lanes.new()</tt> is a "generator" for
    launching any number of lanes. They will share code, options, initial globals,
    but the particular arguments may vary. Only calling the generator function
    actually launches a lane, and provides a handle for controlling it.
</p><p>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>str= lane_h.state</code>
</table>

<p>The current execution state of a lane can be read via its <tt>state</tt>
member, providing one of these values:

    <table>
        <tr><td width=40><td><tt>"pending"</tt></td><td>not started, yet</td></tr>
        <tr><td/><td><tt>"running"</tt></td><td>running</td></tr>
        <tr><td/><td><tt>"waiting"</tt></td><td>waiting at <tt>receive()</tt></td></tr>
        <tr><td/><td><tt>"done"</tt></td><td>finished executing (results are ready)</td></tr>
        <tr><td/><td><tt>"error"</tt></td><td>met an error (reading results will propagate it)</td></tr>
        <tr><td/><td><tt>"cancelled"</tt></td><td>received cancellation and finished itself</td></tr>
    </table>
</@>


<!-- results +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="results">Results</h2>

<p>A lane can be waited upon by reading its results; this will also make sure
the lane has stopped execution.
</p><p>
The lane's results are available as an array of <tt>[1..N]</tt> indices. 
Reading any of them will make sure the thread has been completed. 
<tt>lane_h:unpack()</tt> can be used to get all the results at once, and/or
if a timeout is required.
</p><p>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>[val]= lane_h[1]</code>
</table>
<p>
Makes sure lane has finished, and gives its first (maybe only) return value.
Other return values will be available in other <tt>lane_h</tt> indices.
</p>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>[...]= lane_h:unpack( [wait_secs=-1] )</code>
</table>
<p>
Returns <tt>nil</tt> if the lane hasn't finished before timeout. Otherwise
pends until the lane finishes, and returns the values.
</p>
<!--
<p>
Results can be read for a cancelled lane, too. This allows getting the last
contents of a lane's globals, to be put aside for consequtive resurrection of 
the thread (maybe on some other machine, even!).
</p>
-->

<p>
NOTE: If you use timeouts, either make sure your lane main function returns
a value (so you can defer between timeout-return and done-return), or use the
<tt>.state</tt> value (below).
</p>
<p>
NOTE: One cannot use <tt>unpack()</tt> for reading a lane return values.
It will always give <tt>nil</tt> and won't wait for the lane to finish.
</p>


<!-- errors +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="errors">Error recovery</h2>

<p>If your lane code hits an error, it does not instantly affect other running
lanes, neither report the error anywhere. Only once the lane's results are
acquired, the error is propagated to the reading lane.
</p>
<p>To check the error status without risking propagation of the checking Lua
state, see <tt>error</tt> value of the lane handle.
</p>

<p>
<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>[str]= lane_h.error</code>
</table>

<p>If a lane has met an error, this member will give the error value (normally
a string, but not necessarily). If the lane is still executing, or has ended
without error, the value will be <tt>nil</tt>.
</p>


<!-- cancelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="cancelling">Cancelling</h2>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>lane_h:cancel( [return_state_bool] )</code>
</table>

<p>Cancels the substate execution, asyncronously. Cancellation will take
    effect the next time substate calls <tt>receive()</tt> or after executing
    max. <tt>cancelstep</tt> statements.
</p><p>
    If <tt>return_state</tt> is true, the lane's return value will be <tt>nil, 
    tbl</tt>. Normally, a cancelled lane gives all <tt>nil</tt> as results.
</p>


<!-- lindas +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="lindas">Lindas</h2>

<p>Communications between lanes is performed via Linda tuple spaces. Other,
more specified constructs (FIFOs, keeper tables) can be built on top of these.
</p>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>H= lanes.linda()</code>
    <br/><br/>
    <code>bool= H:send( key, val [,timeout_secs] )</code>
    <br/>
    <code>[val [,key]]= H:receive( key [, ...] [,timeout_secs=-1] )</code>
    <br/><br/>
    <code>void= H:set( key [,val] )</code>
    <br/>
    <code>[val]= H:get( key )</code>
</table>

<p>In sending to a vacant slot, the <tt>value</tt> is written, and <tt>true</tt>
returned. If the slot is not vacant, <tt>timeout_secs</tt> defines the 
behaviour:
<ul>
    <li>Queuing (default). Value is queued to be set next time the slot is read
        (emptied).
    </li>
    <li>Timeout. If <tt>timeout_secs</tt> is given, the writing lane will pend
        until slot will be available (all queued values consumed first).
        Returns <tt>false</tt> on timeout. Use 0.0 for instant check (no wait)
        and -1.0 for eternal wait.
    </li>
</ul>
</p><p>
Any number of keys can be waited upon simultaneously, as long as they belong
to the same Linda object. If the last key is numeric, the <tt>timeout_secs</tt>
parameter must be given (otherwise the last key is taken to be the timeout).
Once a value is received, it is consumed from the slot (which may be refilled
from queue or a pending send).
</p><p>
<tt>set</tt> and <tt>get</tt> methods are for accessing the slot without
queuing or consuming. <tt>set</tt> overwrites existing slot value, and any
possible queued entries. <tt>get</tt> reads the current slot entry (or <tt>nil</tt>
for vacant slot), without consuming it. The send/receive and set/get methods
can be used together; get essentially peeking the current situation of a queue.
</p>

<p>The master state must initialize one or more Lindas for its communication
needs, then pass them on as launch parameters to its substates. Any lane that
has gotten a handle may send to or receive from it. Two-way communication can
be provided using a simple Linda, with i.e. keys "in" and "out" (or whatever).
</p>

<p>If multiple Lindas are waited upon, they don't have any particular priority.
Priority queues can be implemented using multiple Lindas (or FIFOs) or by
zero timeout calls.
</p>

<p>The <code>read</code> function reads the current value (if any) of a Linda
key, without removing it.
</p>


<hr/>
<h4>FIFOs and Keeper tables</h4>

<p>Other multithreading constructs s.a. simple FIFOs and shared memory
"keeper tables" can easily be constructed on top of the Linda mechanism.
See <tt>samples/*.lua</tt>.
</p>


<!-- FIFOs +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<!--
<hr/>
<h3 id="fifos">FIFOs</h3>

<p>FIFO queues are a simpler case of Linda. They will use up the keys "\0FIFOx"
(1..N) automatically.
</p>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>F= lanes.fifo( [linda_h] )</code>
    <br/><br/>
    <code>F:send( val [, ...] )</code>
    <br/>
    <code>[val]= F:receive( [wait_secs=-1] )</code>
    <br/>
    <code>[val]= F:peek()</code>
</table>

<p>If you want to wait for multiple FIFOs, you'll need to use Linda instead.
</p>
-->

<!-- keeper states +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<!--
<hr/>
<h3 id="keepers">Keeper tables</h3>

<p>Keeper tables allow table-like access shared by multiple lanes. They are
internally based on the Linda mechanism.
</p>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>K= lanes.keeper( [linda_h] )</code>
    <br/><br/>
    <code>K[key]= val</code>
    <br/>
    <code>val= K[key]</code>
</table>

<p>The master state must initialize one or more keepers for its communication
needs, then pass them on as launch parameters to its substates. Keepers are
valid throughout the lifespan of the master (or until it sets them to <tt>nil</tt>).
</p>

<pre>
  local K= lanes.keeper()   -- initiates a new keeper table
    ...
  K.a= 10
  K.b= 20
    ...
  K.c= { 1,2,3, text='day' }
    ...
  K.c.some= 55     -- NO, silently ignored!
</pre>

<p>Only the first level of indexing is used by the keeper system, and the keys
need to be either boolean, numerical or string. Tables values 
are read and written atomically, the whole table at once. If you say
<tt>'K.c.text= nil'</tt> it won't change the kept data. It will read the
existing <tt>K.c</tt> to you and set your local copy's <tt>text</tt> field.
This is not what you want.
</p>

<p>If you want to wait for keeper table events, initialize the keeper with
a Linda handle. You can use the Linda handle for waiting.
</p>
-->


<!-- granularity +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h3 id="granularity">Granularity</h3>

<p>You can use a single Linda for all of a program's communications needs,
but you can also create multiple Lindas. Locking granularity is defined by
this decision; each access to a Linda (or a FIFO / keeper table based upon it)
will wake up all the lanes waiting upon a read/write on that Linda. This
means, generally, that it is good to group Lindas according to your program's
logical structure and needs. Waiting for multiple keys can only be achieved
for keys belonging to the same Linda.
</p>


<!-- timers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="timers">Timers</h2>

<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
    <code>= lanes.timer( linda_h, key_val [,first_secs_num [,repeat_secs_num]] )</code>
</table>

<p>
Sets or re-sets a timer. When the given time has passed, the specific Linda 
<tt>key</tt> will be set to the current <i>wall clock</i> time (same as
<tt>os.time()</tt>). If <tt>repeat</tt> is given, the timer will continue to
go off after the given interval. Setting a certain timer (linda, key pair)
again will reset that timer.
</p><p>
Timer keys can be waited upon using regular <tt>linda:receive()</tt>. Values are set, 
not queued, so missing a beat is possible. In this case, the set value will be 
useful to know the actual time passed.
</p><p>
<tt>interval_secs</tt> can be fractional s.a. 0.001 for being informed 1000 
times a second (maybe unrealistic; make that 0.01 and 100).
</p><p>
<tt>first_secs</tt> 0.0 makes one instant hit, allowing the timer to self-adjust
i.e. to time every even minutes.
</p><p>
Timers are handled by a single, hidden Lua state that waits most of its time
asleep.
</p>


<!-- others +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="other">Other issues</h2>

<h3>Limitations on data passing</h3>

<p>Data passed between separate states (either as starting parameters, return
values or via keeper tables) must conform to the following:
</p>
<p><ul>
    <li>booleans, numbers, strings, and tables of those (including subtables) can be
  passed</li>
  <li>duplicate references in tables are 'opened' (passed by value)</li>
  <li>there must be no cycles in the passed tables</li>
  <li>full userdata is passed on as a light copy (just the pointer); sender
  remains in charge of the lifespan, and must not let the value be GC'ed if
  other lanes are still using it.</li>
  <li>coroutines cannot be passed</li>
  <li>more restrictions may apply (to be added here later on :)</li>
</ul>


<h3>Required of module makers</h3>

<p>
Most Lua extension modules should work unaltered with Lanes.
</p><p>
If the module simply ties C side features to Lua, everything is fine without
alterations. The <tt>lua_open()</tt> entry point will be called separately for each
lane, where the module is <tt>require</tt>'d.
</p><p>
If it, however, also does one-time C side initializations, these
should be covered into a one-time-only construct such as below. Note that the
module does not need to do proper OS side locking; Lanes serializes
calls to <tt>require</tt>, so no two module initializations will happen at the
same time. You may do proper OS locking, if you want.
</p><p>

<table><tr><td width=40>
    <td bgcolor="#ffffe0">
<pre>
 int luaopen_module( lua_State *L )
 {
    static char been_here;  /* 0 by ANSI C */
    
    /* Calls to 'require' serialized by Lanes; this is safe.&nbsp;&nbsp;
    */
    if (!been_here) {
        been_here= 1;
        ... one time initializations ...
    }
    
    ... binding to Lua ...
 }
</pre>
</td></tr></table>
</p>


<!-- change log +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>
<h2 id="changes">Change log</h2>

<p>
Changes by version:

<ul>
    <li>Jun-2008:</li>
    <ul>
        <li><tt>lanes.new</tt> (renamed from <tt>lanes.prepare</tt>)
        </li>
        <li>Keeper tables introduced; replaces <tt>send</tt>, 
                <tt>receive</tt>, grouping, tubes and serialization (all discontinued)
        </li>
        <li><tt>lane.wait(lane_h)</tt> replaces <tt>lane_h:results()</tt> 
    </ul>
</ul>


<!-- footnotes +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<hr/>

<p>For feedback, questions and suggestions:
<UL>
    <li><A HREF="http://luaforge.net/projects/lanes">Lanes @ LuaForge</A></li>
    <li><A HREF="mailto:akauppi@gmail.com">the author</A></li>
</UL>
</p>

<font size="-1">
<p>
1) Extension modules get loaded only once, but they will get <i>initialized</i>
multiple times, once per each Lua state. If the module C code uses global and/or
static variables during its initialization, it may not work with Lanes. The
solution is to use Thread Local Storage, or avoid the globals some other way.
</p>
</font>

</body>
</html>
